package bll

import (
	"bytes"
	"encoding/binary"
	"gitlab.local/backend/proto/dto"
	"hash/crc32"
)

var Upgrade = &upgrade{}

// 服务端向设备发起升级
type upgrade struct{}

type PacketBSC22 struct {
	Magic       uint16
	Len         uint16
	ID          uint64
	DeviceType  uint8
	Cmd         uint8
	BindAddress uint32
	BindLength  uint32
	Body        []byte
	Crc32       uint32
}

/*
		magic	  length	id	  device	cmd	  bin_address	  bin_length	data	crc32
	  2Byte	  2Byte	 8Byte	1Byte	  1Byte	  4Byte	       4Byte	  nByte	  4Byte
*/

/*
		magic	  length	id	  device	cmd	  bin_address	  bin_length	data	crc32
	  2Byte	  2Byte	 8Byte	1Byte	  1Byte	  4Byte	       4Byte	  nByte	  4Byte
*/
func BuildPacket(bsc22 *dto.UpgradeBSC22Data) *PacketBSC22 {
	p := &PacketBSC22{
		Magic:       binary.BigEndian.Uint16([]byte{0x5a, 0xa5}),
		ID:          bsc22.Id,
		DeviceType:  uint8(bsc22.DeviceType),
		Cmd:         uint8(bsc22.UpgradeCmd),
		BindLength:  bsc22.BindLength,
		BindAddress: bsc22.BindAddress,
		Len:         uint16(8) + uint16(1) + uint16(1) + uint16(4) + uint16(4) + uint16(len(bsc22.Body)) + uint16(4),
		Body:        bsc22.Body,
	}

	crc32Data := p.ToHexBytes(true)
	p.Crc32 = crc32.ChecksumIEEE(crc32Data)
	return p
}

func (p *PacketBSC22) ToHexBytes(args ...any) []byte {

	var (
		crcCalculate bool
		buffer       bytes.Buffer
		order        binary.ByteOrder = binary.LittleEndian
	)
	if len(args) == 1 {
		crcCalculate = args[0].(bool)
	}

	_ = binary.Write(&buffer, order, p.Magic)
	_ = binary.Write(&buffer, order, p.Len)
	_ = binary.Write(&buffer, order, p.ID)
	_ = binary.Write(&buffer, order, p.DeviceType)
	_ = binary.Write(&buffer, order, p.Cmd)
	_ = binary.Write(&buffer, order, p.BindAddress)
	_ = binary.Write(&buffer, order, p.BindLength)
	_ = binary.Write(&buffer, binary.LittleEndian, p.Body)
	if !crcCalculate {
		_ = binary.Write(&buffer, order, p.Crc32)
	}

	return buffer.Bytes()
}
